﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Xml;
using System.Xml.XPath;
using System.IO;
using System.Runtime.CompilerServices;
using System.Security;

namespace MyDLL
{
    /// Code By D.S.Qiu  
    /* 
     * 具体规则可参考：http://www.w3school.com.cn/xpath/index.asp 
     * 或者：https://msdn.microsoft.com/en-us/library/ms256471(v=vs.110).aspx 
     * https://msdn.microsoft.com/en-us/library/ms256453(v=vs.110).aspx 
     * 
     * 1.节点 
     * a)./author 或 author  当前节点的所有<author>子节点 
     * b)/author             根节点的所有<author>子节点 
     * c)//author            根节点的所有<author>节点   注 .//author 当前节点所有<author>节点 
     * d).                   选取当前节点 
     * e)..                  选取当前节点的父节点 
     * f)@                   选取属性 

    author/first-name  All <first-name> elements within an <author> element of the current context node. 
    bookstore//title  All <title> elements one or more levels deep in the <bookstore> element (arbitrary descendants). 
    .//title  All <title> elements one or more levels deep in the current context. Note that this situation is essentially the only one in which the period notation is required. 

    @style  The style attribute of the current element context. 
    price/@exchange The exchange attribute of <price> elements within the current context. 
    book/@style The style attribute of all <book> elements. 
    Note that the following example is not valid, because an attribute cannot have any children. 
    price/@exchange/total 
     * 
     * 2.谓词 
     * a)[]                  谓语被嵌在方括号中 
     *     /bookstore/book[price>35.00]  选取 bookstore 元素的所有 book 元素，且其中的 price 元素的值须大于 35.00。 
     *     /bookstore/book[position()<3] 选取最前面的两个属于 bookstore 元素的子元素的 book 元素。 
     *     //title[@lang='eng'] 选取所有 title 元素，且这些元素拥有值为 eng 的 lang 属性。 
     *     book[excerpt]  All <book> elements that contain at least one <excerpt> element. 
           book[excerpt]/title  All <title> elements inside <book> elements that contain at least one <excerpt> element. 
           book[excerpt]/author[degree]  All <author> elements that contain at least one <degree> element, and are inside of <book> elements that contain at least one <excerpt> element. 
           book[author/degree]  All <book> elements that contain at least one <author> element with at least one <degree> child element. 
           book[excerpt][title] All <book> elements that contain at least one <excerpt> element and at least one <title> element. 

     * b)*                   匹配任何元素节点 
     * c)@*                  匹配任何属性节点 
     * d)node()              匹配任何类型的节点 
     * 
     * 3.轴 
     * a)ancestor   选取当前节点的所有先辈（父、祖父等）。 
     * b)ancestor-or-self   选取当前节点的所有先辈（父、祖父等）以及当前节点本身。 
     * c)attribute  选取当前节点的所有属性。 
     * d)child  选取当前节点的所有子元素。 
     * e)descendant 选取当前节点的所有后代元素（子、孙等）。 
     * f)descendant-or-self 选取当前节点的所有后代元素（子、孙等）以及当前节点本身。 
     * g)following  选取文档中当前节点的结束标签之后的所有节点。 
     * h)namespace  选取当前节点的所有命名空间节点。 
     * i)parent 选取当前节点的父节点。 
     * j)preceding  选取文档中当前节点的开始标签之前的所有节点。 
     * k)preceding-sibling  选取当前节点之前的所有同级节点。 
     * l)self   选取当前节点。 
     * 步的语法： 
         轴（axis） 
         定义所选节点与当前节点之间的树关系 
         节点测试（node-test） 
         识别某个轴内部的节点 
         零个或者更多谓语（predicate） 
         更深入地提炼所选的节点集 
         轴名称::节点测试[谓语] 
        实例 
        child::book 选取所有属于当前节点的子元素的 book 节点。 
        attribute::lang 选取当前节点的 lang 属性。 
        child::*    选取当前节点的所有子元素。   和 * 一致 
        child::text()   选取当前节点的所有文本子节点。 和 . 一致 
        child::node()   选取当前节点的所有子节点。   和 .. 一致 
     * 
     * 
    Precedence 
    Precedence order (from highest precedence to lowest) between Boolean and comparison operators is shown in the following table. 

    Precedence  Operators   Description 
    1 ( ) Grouping 
    2 [ ] Filters 
    3 /   Path operations 
      // 
    4 &lt;  Comparisons 
      &lt;= 
      &gt; 
      &gt;= 
    5 = Comparisons 
      != 
    6 | Union 
    7 not() Boolean not 
    8 and Boolean and 
    9 or  Boolean or 
     * 
     */
    public class XML_Commons
    {
        private XmlReader xmlReader = null;
        private XmlDocument xmlDoc = null;
        private XmlNode root = null;
        private string fileName="";

        public XML_Commons(string fileName_Full)
        {
            //xmlReader = new XmlTextReader(fileName_Full);
            xmlDoc = new XmlDocument();
            //xmlDoc.Load(xmlReader);
            xmlDoc.Load(fileName_Full);
            root = xmlDoc.DocumentElement;
            fileName = fileName_Full;
        }
        /// <summary>
        /// 将xml文件各节点（所有符合名称的节点）的InnerText用字符串数组的形式返回。
        /// </summary>
        /// <param name="NodeNames">节点名称字符串</param>
        /// <returns>返回字符串数组</returns>
        public string[] XmlToStringArrByName_AnyNodes(string[] NodeNames)
        {
            string[] resArr = new string[NodeNames.Length];
            XmlNode nodeTemp = null;

            for (int i = 0; i < NodeNames.Length; i++)
            {
                nodeTemp = root.SelectSingleNode("//" + NodeNames[i]);
                if (nodeTemp != null)
                {
                    resArr[i] = nodeTemp.InnerText;
                }
            }
            return resArr;
        }

        /// <summary>
        /// 根据xpath返回指定节点的InnerText。
        /// </summary>
        /// <param name="xpath">Xpath</param>
        /// <returns>返回的InnerText</returns>
        public string Xml_NodeInnerText_ToStringByXpath(string xpath)
        {
            string resStr = "";            
            XmlNode nodeTemp = root.SelectSingleNode(xpath);
            if (nodeTemp != null)
            {
                resStr = nodeTemp.InnerText;
            }
            return resStr;
        }

        /// <summary>
        /// 根据xpath返回指定节点的Attribute Text。
        /// </summary>
        /// <param name="xpath">指定节点的Xpath</param>
        /// <param name="attributeName">属性名称</param>
        /// <returns>返回的Attribute Text</returns>
        public string Xml_AttributeText_ToStringByXpath(string xpath, string attributeName)
        {
            string resStr = "";
            XmlNode nodeTemp = root.SelectSingleNode(xpath);
            XmlElement elementTemp = (XmlElement)nodeTemp;
            if (nodeTemp != null)
            {
                resStr = elementTemp.GetAttribute(attributeName).ToString();
            }
            return resStr;
        }

        /// <summary>
        /// 以字符串数组的形式返回指定母节点下所有指定子节点的InnerText。
        /// </summary>
        /// <param name="xpath_ToParent">母节点的Xpath</param>
        /// <param name="NodeNames_Children">子节点的名字（或分段Xpath，不包括最前面的“/”）。</param>
        /// <returns>返回字符串数组</returns>
        public string[] Xml_NodesInnerText_ToStringArrByXpath_ToParentRetrieveChildren(string xpath_ToParent,string[] NodeNames_Children)
        {
            string[] resArr = new string[NodeNames_Children.Length];
            string xpath_Child = "";
            for (int i = 0; i < NodeNames_Children.Length; i++)
            {
                xpath_Child = xpath_ToParent + "/" + NodeNames_Children[i];
                resArr[i] = Xml_NodeInnerText_ToStringByXpath(xpath_Child);
            }
            return resArr;
        }

        /// <summary>
        /// 以字符串数组列表的形式返回指定母节点的指定属性Text和其下所有指定子节点的InnerText。
        /// </summary>
        /// <param name="xpath_ToParent">母节点的Xpath</param>
        /// <param name="Attributes_Parent">母节点中的属性名称</param>
        /// <param name="NodeNames_Children">子节点的名称（或分段Xpath，不包括最前面的“/”）。</param>
        /// <returns>返回字符串数组列表</returns>
        public List<string[]> Xml_ParentAttributes_Plus_ChildrenNodesInnerText_ToStringArrListByXpath_ToParentRetrieveChildren(string xpath_ToParent, string[] Attributes_Parent, string[] NodeNames_Children)
        {
            List<string[]> resList = new List<string[]>();
            string[] resArr = new string[Attributes_Parent.Length];
            for (int i = 0; i < Attributes_Parent.Length; i++)
            {
                resArr[i]= Xml_AttributeText_ToStringByXpath(xpath_ToParent, Attributes_Parent[i]);
            }
            resList.Add(resArr);
            resArr = new string[NodeNames_Children.Length];

            for (int i = 0; i < NodeNames_Children.Length; i++)
            {
                string xpath_Child = xpath_ToParent + "/" + NodeNames_Children[i];
                resArr[i] = Xml_NodeInnerText_ToStringByXpath(xpath_Child);
            }
            resList.Add(resArr);
            return resList;
        }

        /// <summary>
        /// 以字符串数组的形式返回所有符合名字的节点的InnerText。
        /// </summary>
        /// <param name="xpath">节点的xpath</param>
        /// <returns>返回的字符串数组</returns>
        public string[] AllSelectedNodesInnerTexts(string xpath)
        {
            XmlNodeList nodeListTemp = root.SelectNodes(xpath);
            string[] resArr = new string[nodeListTemp.Count];
            for (int i = 0; i < resArr.Length; i++)
            {
                resArr[i] = nodeListTemp[i].InnerText.ToString();
            }
            return resArr;
        }

        /// <summary>
        /// 以字符串的形式返回第一个符合名字的节点的InnerText。
        /// </summary>
        /// <param name="xpath">节点的xpath</param>
        /// <returns>返回的字符串</returns>
        public string SingleSelectedNodesInnerText(string xpath)
        {
            string[] resArr = AllSelectedNodesInnerTexts(xpath);
            return resArr[0];
        }

        /// <summary>
        /// 以字符串数组列表的形式返回所有符合名字的节点的指定属性。
        /// </summary>
        /// <param name="xpath">指定节点的xpath</param>
        /// <param name="attributeNames">属性数组</param>
        /// <returns>返回的字符串数组列表</returns>
        public List<string[]> AllSelectedNodesSelectedAttributes(string xpath, string[] attributeNames)
        {
            List<string[]> resList = new List<string[]>();
            XmlNodeList nodeListTemp = root.SelectNodes(xpath);
            for (int i = 0; i < nodeListTemp.Count; i++)
            {
                string[] resArr = new string[attributeNames.Length];
                XmlElement elementTemp = (XmlElement)nodeListTemp[i];
                for (int j = 0; j < attributeNames.Length; j++)
                {
                    resArr[j] = elementTemp.GetAttribute(attributeNames[j]).ToString();
                }
                resList.Add(resArr);
            }

            return resList;
        }

        /// <summary>
        /// 删除一个或多个节点。
        /// </summary>
        /// <param name="xpath">节点的Xpath</param>
        public void DeleteNodes(string xpath)
        {
            XmlNodeList nodeListTemp = root.SelectNodes(xpath);
            for (int i = 0; i < nodeListTemp.Count; i++)
            {
                nodeListTemp[i].ParentNode.RemoveChild(nodeListTemp[i]);
            }
            xmlDoc.Save(fileName);
        }

        /// <summary>
        /// 将字符串数组保存进已经存在的xml文件中，不添加新的节点，仅修改节点的InnerText。
        /// </summary>
        /// <param name="xpath_ToParent">母节点的Xpath</param>
        /// <param name="strArr_Nodes">字符串数组</param>
        /// <param name="NodeNames_Children">子节点的名字数组（或分段Xpath，不包括最前面的“/”）。</param>
        public void UpdateXmlNodesByName_ToParent_UpdateChildren(string xpath_ToParent, string[] strArr_Nodes, string[] NodeNames_Children)
        {
            for (int i = 0; i < NodeNames_Children.Length; i++)
            {
                string xpath_Child = xpath_ToParent + "/" + NodeNames_Children[i];
                XmlNode nodeTemp = root.SelectSingleNode(xpath_Child);
                if (nodeTemp != null)
                {
                    nodeTemp.InnerText = strArr_Nodes[i];
                }                
            }
            xmlDoc.Save(fileName);
        }

        /// <summary>
        /// 将字符串数组保存进已经存在的xml文件中，不添加新的节点，仅修改指定节点的指定Attributes的内容。
        /// </summary>
        /// <param name="xpath_ToParent">节点的Xpath</param>
        /// <param name="strArr_Attributes">待添加的Attributes的内容</param>
        /// <param name="AttributeNames">节点的Attributes的names</param>
        public void UpdateXmlAttributesByName_ToParent(string xpath_ToParent, string[] strArr_Attributes, string[] AttributeNames)
        {
            XmlElement eleTemp = (XmlElement)root.SelectSingleNode(xpath_ToParent);
            if (eleTemp != null)
            {
                for (int i = 0; i < AttributeNames.Length; i++)
                {
                    eleTemp.SetAttribute(AttributeNames[i], strArr_Attributes[i]);
                }
            }            
            xmlDoc.Save(fileName);
        }

        /// <summary>
        /// 将字符串数组保存进已经存在的xml文件中，不添加新的节点，仅修改节点的InnerText，以及母节点的Attributes。
        /// </summary>
        /// <param name="xpath_ToParent">母节点的Xpath</param>
        /// <param name="strArr_Attributes">待添加母节点的Attributes的内容</param>
        /// <param name="AttributeNames_Parent">母节点的Attributes的names</param>
        /// <param name="strArr_Nodes">待添加的子节点的内容</param>
        /// <param name="NodeNames_Children">子节点的名字数组（或分段Xpath，不包括最前面的“/”）。</param>
        public void UpdateXmlAttributes_And_ChildrenNodesByName_ToParent(string xpath_ToParent, string[] strArr_Attributes, string[] AttributeNames_Parent, string[] strArr_Nodes, string[] NodeNames_Children)
        {
            UpdateXmlAttributesByName_ToParent(xpath_ToParent, strArr_Attributes, AttributeNames_Parent);
            UpdateXmlNodesByName_ToParent_UpdateChildren(xpath_ToParent, strArr_Nodes, NodeNames_Children);
        }

        /// <summary>
        /// 添加子节点。
        /// </summary>
        /// <param name="xpath_ToParent">母节点的Xpath</param>
        /// <param name="nodeName_Child">子节点的名称</param>
        /// <param name="innerText">子节点的InnerText，可省略，默认为空。</param>
        public void AppendChild(string xpath_ToParent, string nodeName_Child, string innerText = "")
        {
            XmlNode nodeParent = root.SelectSingleNode(xpath_ToParent);
            XmlNode nodeChild = xmlDoc.CreateElement(nodeName_Child);
            if (innerText != "")
            {
                nodeChild.InnerText = innerText;
            }
            nodeParent.AppendChild(nodeChild);
        }

        /// <summary>
        /// 为节点添加属性。
        /// </summary>
        /// <param name="xpath">指定节点的Xpath</param>
        /// <param name="attributeNames">属性名称数组</param>
        /// <param name="attributeInnerTexts">属性的InnerText数组</param>
        public void CreateAttributes(string xpath, string[] attributeNames, string[] attributeInnerTexts)
        {
            XmlElement eleTemp = (XmlElement)root.SelectSingleNode(xpath);
            for (int i = 0; i < attributeNames.Length; i++)
            {
                XmlAttribute attributeTemp = xmlDoc.CreateAttribute(attributeNames[i]);
                attributeTemp.InnerText = attributeInnerTexts[i];
                eleTemp.SetAttributeNode(attributeTemp);
            }
        }

        /// <summary>
        /// 添加一个子节点，并为该子节点添加属性。
        /// </summary>
        /// <param name="xpath_ToParent">母节点的Xpath</param>
        /// <param name="nodeName_Child">子节点的名称</param>
        /// <param name="attributeNames">子节点属性的名称数组</param>
        /// <param name="attributeInnerTexts">子节点属性的InnerText数组</param>
        /// <param name="innerText_Node">子节点的InnerText，可省略，默认为空</param>
        public void AppendChild_CreateAttributes(string xpath_ToParent,string nodeName_Child, string[] attributeNames, string[] attributeInnerTexts, string innerText_Node = "")
        {
            AppendChild(xpath_ToParent, nodeName_Child, innerText_Node);
            string xpath = xpath_ToParent + "/" + nodeName_Child + "[last()]";
            CreateAttributes(xpath, attributeNames, attributeInnerTexts);
        }

        /// <summary>
        /// 添加一个子节点，并为该子节点添加属性，再为该子节点添加若干孙节点。
        /// </summary>
        /// <param name="xpath_ToParent">母节点的Xpath</param>
        /// <param name="nodeName_Child">子节点的名称</param>
        /// <param name="attributeNames">子节点属性的名称数组</param>
        /// <param name="attributeInnerTexts">子节点属性的InnerText数组</param>
        /// <param name="nodeNames_GrandChildren">孙节点的名称数组</param>
        /// <param name="innerTexts_GrandChildrenNode">孙节点的InnerText数组</param>
        /// <param name="innerText_ChildNode">子节点的InnerText，可省略，默认为空</param>
        public void AppendChild_CreateAttributes_CreateGrandChildrenNodes(string xpath_ToParent, string nodeName_Child, string[] attributeNames, string[] attributeInnerTexts, string[] nodeNames_GrandChildren, string[] innerTexts_GrandChildrenNode, string innerText_ChildNode = "")
        {
            AppendChild_CreateAttributes(xpath_ToParent, nodeName_Child, attributeNames, attributeInnerTexts, innerText_ChildNode);
            for (int i = 0; i < nodeNames_GrandChildren.Length; i++)
            {
                string xpath = xpath_ToParent + "/" + nodeName_Child + "[last()]";
                AppendChild(xpath, nodeNames_GrandChildren[i], innerTexts_GrandChildrenNode[i]);
            }
        }
    }
    public class XmlUtils
    {
        public static StringBuilder xpath = new StringBuilder();
        public static XmlDocument xmlDoc = new XmlDocument();
        public static XmlElement root = null;
        public static void AddCommint(string commit)
        {
            xpath.Append(commit);
        }
        public static void AddNode(string name)
        {
            xpath.Append("/" + name);
        }
        public static void AddNodeRegardlessPosition(string name)
        {
            xpath.Append("//" + name);
        }
        public static void AddNodeByIndex(string name, string index)
        {
            xpath.Append("/" + name + "[" + index + "]");
        }
        public static void AddNodeByIndexRegardlessPosition(string name, string index)
        {
            xpath.Append("//" + name + "[" + index + "]");
        }
        public static void AddNodeByValue(string name, string value, string operatorstr = "=")
        {
            xpath.Append("[" + name + operatorstr + value + "]");
        }
        public static void AddIndex(string index)
        {
            xpath.Append("[" + index + "]");
        }
        public static void AddAttribute(string name)
        {
            xpath.Append("[@" + name + "]");
        }
        public static void AddAttributeByValue(string name, string value, string operatorstr = "=")
        {
            xpath.Append("[@" + name + operatorstr + value + "]");
        }
        public static void AddAnyNode()
        {
            xpath.Append("/*");
        }
        public static void AddAnyNodeRegardlessPosition()
        {
            xpath.Append("//*");
        }
        public static void AddAnyAttribute()
        {
            xpath.Append("[@*]");
        }
        public static void Load(string filename)
        {
            xmlDoc.Load(filename);
            root = xmlDoc.DocumentElement;
        }

        public static XmlNodeList Commit(string commit = null)
        {
            XmlNodeList xn = null;
            if (commit != null)
            {
                xn = root.SelectNodes(commit);
            }

            else if (xpath.Length != 0)
            {
                xn = root.SelectNodes(XmlUtils.xpath.ToString());
                xpath.Clear();
            }

            return xn;
        }
        public void addElement(string path, string node_root, string node_name, string node_text, string att_name, string att_value)
        {
            Load(path);

            XmlNodeList nodeList = xmlDoc.SelectSingleNode(node_root).ChildNodes;//获取bookstore节点的所有子节点  
            //判断是否有节点,有节点就遍历所有子节点,看看有没有重复节点,没节点就添加一个新节点  
            if (nodeList.Count > 0)
            {
                foreach (XmlNode xn in nodeList)//遍历所有子节点   
                {
                    XmlElement xe = (XmlElement)xn;//将子节点类型转换为XmlElement类型   
                    if (xe.GetAttribute(att_name) != att_value)
                    {
                        XmlNode xmldocSelect = xmlDoc.SelectSingleNode(node_root);   //选中根节点  
                        XmlElement son_node = xmlDoc.CreateElement(node_name);    //添加子节点   
                        son_node.SetAttribute(att_name, att_value);     //设置属性  
                        son_node.InnerText = node_text;    //添加节点文本  
                        xmldocSelect.AppendChild(son_node);       //添加子节点  
                        xmlDoc.Save(path);          //保存xml文件  
                        break;
                    }
                }

            }
            else
            {
                XmlNode xmldocSelect = xmlDoc.SelectSingleNode(node_root);   //选中根节点  
                XmlElement son_node = xmlDoc.CreateElement(node_name);    //添加子节点   
                son_node.SetAttribute(att_name, att_value);     //设置属性  
                son_node.InnerText = node_text;    //添加节点文本  
                xmldocSelect.AppendChild(son_node);       //添加子节点  
                xmlDoc.Save(path);          //保存xml文件  
            }
        }

        /// <summary>  
        /// 修改节点的内容  
        /// </summary>  
        /// <param name="path">xml文件的物理路径</param>  
        /// <param name="node_root">根节点名称</param>  
        /// <param name="new_text">节点的新内容</param>  
        /// <param name="att_name">节点的属性名</param>  
        /// <param name="att_value">节点的属性值</param>  
        public void UpdateElement(string path, string node_root, string new_text, string att_name, string att_value)
        {
            Load(path);
            XmlNodeList nodeList = xmlDoc.SelectSingleNode(node_root).ChildNodes;//获取bookstore节点的所有子节点   
            foreach (XmlNode xn in nodeList)//遍历所有子节点   
            {
                XmlElement xe = (XmlElement)xn;//将子节点类型转换为XmlElement类型   
                if (xe.GetAttribute(att_name) == att_value)
                {
                    xe.InnerText = new_text;    //内容赋值  
                    xmlDoc.Save(path);//保存   
                    break;
                }
            }

        }

        /// <summary>  
        /// 删除节点  
        /// </summary>  
        /// <param name="path">xml文件的物理路径</param>  
        /// <param name="node_root">根节点名称</param>  
        /// <param name="att_name">节点的属性名</param>  
        /// <param name="att_value">节点的属性值</param>  
        public void deleteNode(string path, string node_root, string att_name, string att_value)
        {
            Load(path);
            XmlNodeList nodeList = xmlDoc.SelectSingleNode(node_root).ChildNodes;
            XmlNode root = xmlDoc.SelectSingleNode(node_root);
            foreach (XmlNode xn in nodeList)
            {
                XmlElement xe = (XmlElement)xn;
                if (xe.GetAttribute(att_name) == att_value)
                {
                    //xe.RemoveAttribute("name");//删除name属性   
                    xe.RemoveAll();//删除该节点的全部内容   
                    root.RemoveChild(xe);
                    xmlDoc.Save(path);//保存   
                    break;
                }

            }
        }
    }
    public static class XmlExtension
    {


        public static XmlNode UpdateAttribute(this XmlNode node, string name, string value)
        {
            XmlAttribute newAttr = node.OwnerDocument.CreateAttribute(name);
            newAttr.Value = value;
            //xn.Attributes.RemoveNamedItem(attributeValues[i]);  
            node.Attributes.SetNamedItem(newAttr);     //设置属性  
            return node;
        }

/*        using UnityEngine;
        public static XmlNode DeleteAttribute(this XmlNode node, string name)
    {
        if (node.Attributes == null)
        {
            Debug.Log("This XMLNode have no attribute!");
        }
        else
        {
            XmlAttribute attribute = node.Attributes[name];
            node.Attributes.Remove(attribute);
        }
        return node;
    }

    public static XmlNode DeleteElement(this XmlNode node, string xpath)
    {
        XmlNodeList rootNodes = node.SelectNodes(xpath);
        if (rootNodes == null || rootNodes.Count == 0)
        {
            Debug.Log(string.Format("Not Found the node {0} in the XmlNode!", xpath));
            return node;
        }
        //遍历所有子节点  
        foreach (XmlNode xn in rootNodes)
        {
            node.RemoveChild(xn);
        }
        return node;
    }

    /// <summary>  
    ///   
    /// </summary>  
    /// <param name="node"></param>  
    /// <param name="xpath"></param>  
    /// <param name="nodeName"></param>  
    /// <param name="nodeText"></param>  
    /// <returns>方便chain call</returns>  
    public static System.Xml.XmlElement AppendElement(this XmlNode node, string xpath, string nodeName, string nodeText)
    {
        XmlNode rootNode = node.SelectSingleNode(xpath);
        if (rootNode == null)
        {
            Debug.Log(string.Format("Not Found the node {0} in the XmlNode!", xpath));
            return null;
        }

        XmlElement sonNode = node.OwnerDocument.CreateElement(nodeName);    //添加子节点  
        sonNode.InnerText = nodeText;
        rootNode.AppendChild(sonNode);       //添加子节点  
        return sonNode;
    }*/

    public static System.Xml.XmlElement AppendElement(this XmlNode node, string nodeName, string nodeText = "")
        {
            XmlElement sonNode = node.OwnerDocument.CreateElement(nodeName);    //添加子节点  
            sonNode.InnerText = nodeText;
            node.AppendChild(sonNode);       //添加子节点  
            return sonNode;
        }
    }

    /// <summary>  
    /// 默认把xml的命名工具都去掉，方便使用 XPath 表达式，保存之后再替换回来  
    /// 所有解析必须在Begin 和 End 之间调用  
    /// </summary>  
    public class XmlUtility
    {

        //using UnityEngine;
        /*public class XPath
        {
            public const string FilterFormat = "[{0}]";
            public const string StepFormat = "{0}::{1}[{2}]";


            private static StringBuilder s_content = new StringBuilder();

            public XPath Clear()
            {
                s_content = new StringBuilder();
                return this;
            }

            public XPath Append(string path)
            {
                s_content.Append(path);
                return this;
            }

            public XPath AppendFormat(string format, params string[] param)
            {
                return Append(string.Format(format, param));
            }

            public XPath AppendNode(string nodeName)
            {
                return Append("/" + nodeName);
            }

            public XPath AppendAnyNode(string nodeName)
            {
                return Append("//" + nodeName);
            }

            public XPath AppendFilter(string filter)
            {
                return AppendFormat(FilterFormat, filter);
            }

            public XPath AppendStep(string axis, string nodeTest = "*", string predicate = "*")
            {
                return AppendFormat(StepFormat, axis, nodeTest, predicate);
            }

        }*/

        public const string Xmlns = "xmlns";
        public const string XmlnsReplace = "xmlns_replace";

        private static XmlDocument xmlDoc = null;//new XmlDocument();  
        private static bool replaceXmlns = false;
        private static string xmlPath;


        /*public static void Begin(string xmlPath, bool replaceXmlns = true)
        {
            XmlUtility.xmlPath = xmlPath;
            XmlUtility.replaceXmlns = replaceXmlns;
            Load(xmlPath, replaceXmlns);
        }*/

        /*public static void End(bool save = true)
        {
            if (save)
                Save(XmlUtility.xmlPath, XmlUtility.replaceXmlns);
            xmlDoc = null;
        }*/

        /*private static void Load(string xmlPath, bool replaceXmlns)
        {
            xmlDoc = new XmlDocument();
            try
            {
                string xmlText = File.ReadAllText(xmlPath);
                //去掉命名空间  
                if (replaceXmlns)
                    xmlText = xmlText.Replace(Xmlns, XmlnsReplace);
                xmlDoc.LoadXml(xmlText);
            }
            catch (Exception ex)
            {
                Debug.LogError("XmlDocument Load Error: " + ex.ToString());
            }
        }*/

        /*private static void Save(string xmlPath, bool replaceXmlns)
        {
            if (xmlDoc == null)
                return;
            try
            {
                xmlDoc.Save(xmlPath);
                //恢复默命名空间  
                if (replaceXmlns)
                {
                    string xmlText = File.ReadAllText(xmlPath);
                    xmlText = xmlText.Replace(XmlnsReplace, Xmlns);
                    File.WriteAllText(xmlPath, xmlText);
                }
            }
            catch (Exception ex)
            {
                Debug.LogError("XmlDocument Save Error: " + ex.ToString());
            }
        }*/


        /*/// <summary>  
        /// The result of the expression (Boolean, number, string, or node set). This maps to Boolean, Double, String, or  
        /// XPathNodeIterator objects respectively.  
        /// 注意：如果返回的是 XPathNodeIterator 不会获得所有元素，必须帝调用MoveNext()才能取得元素  
        /// 查看：https://msdn.microsoft.com/en-us/library/system.xml.xpath.xpathnodeiterator.aspx 的 Remarks  
        /// </summary>  
        /// <param name="xmlPath">Xml path.</param>  
        /// <param name="xpath">Xpath.</param>  
        public static object Evaluate(string xpath)
        {
            //XmlDocument xmlDoc = Load (xmlPath);  
            if (xmlDoc == null)
                return null;
            XPathNavigator navigator = xmlDoc.CreateNavigator();
            try
            {
                XPathExpression expression = navigator.Compile(xpath);
                return navigator.Evaluate(expression);
            }
            catch (Exception ex)
            {
                Debug.LogError("XPath Evalute Error: " + ex.ToString());
                return null;
            }
        }*/


        public static XmlNode FindElement(string xpath)
        {
            //XmlDocument xmlDoc = Load (xmlPath);  
            if (xmlDoc == null)
                return null;
            var test = xmlDoc.SelectNodes(xpath);
            return xmlDoc.SelectSingleNode(xpath);
        }

        public static XmlNodeList FindElements(string xpath)
        {
            //XmlDocument xmlDoc = Load (xmlPath);  
            if (xmlDoc == null)
                return null;
            return xmlDoc.SelectNodes(xpath);
        }


        /*public static void AppendElement(string xpath, string nodeName, string nodeText)
        {
            //XmlDocument xmlDoc = Load (xmlPath);  
            if (xmlDoc == null)
                return;
            xmlDoc.AppendElement(xpath, nodeName, nodeText);
            //xmlDoc.Save (xmlPath);  
        }*/

        /*public static void DeleteElement(string xpath)
        {
            //XmlDocument xmlDoc = Load (xmlPath);  
            if (xmlDoc == null)
                return;
            xmlDoc.DeleteElement(xpath);
            //xmlDoc.Save (xmlPath);  
        }*/

    }
}
